/*
Copyright (C) 1997-2001 Id Software, Inc.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

#ifdef GCCBROKENRELATIVEPATHS
#include "../../ref_soft/r_local.h"
#else
#include "../ref_soft/r_local.h"
#endif

#include "kernel.h"
#include "swis.h"

static int sWidth, sHeight, sRowBytes;
static int lineDouble;

typedef struct
{
  int flags;
  int xres;
  int yres;
  int pixdepth;
  int framerate;
  int modevars[10];
} modespec;

int bank = 1;

int    memBuffer = 1;
void * screenBuffer;
int    screenBufferSize;

/******************************************/
/* SetMode()                              */
/*                                        */
/* Parameters:                            */
/*                                        */
/* Returns:                               */
/******************************************/
static _kernel_oserror * SetMode(int xres, int yres)
{
    _kernel_oserror * e     = NULL;
    int               in[]  = {148, -1};
    modespec          modeblock;
    int               banks;
    int               rowBytes = xres;

    sWidth  = xres;
    sHeight = yres;

    if (xres == 320 && yres == 240)
    {
        yres = 480;
        if (!memBuffer) {
            rowBytes *= 2;
        }
        lineDouble = 1;
    }
    else
    {
        lineDouble = 0;
    }

    modeblock.flags     = 1;
    modeblock.xres      = xres;
    modeblock.yres      = yres;
    modeblock.framerate = -1;
    modeblock.pixdepth  = 3;
    modeblock.modevars[0] = 3;
    modeblock.modevars[1] = 255;
    modeblock.modevars[2] = -1;

    e = _swix(OS_ScreenMode, _INR(0, 1), 0, &modeblock);
    if (!e) e = _swix(OS_RemoveCursors, 0); /* Switch off cursor */
    if (!e) e = _swix(OS_ReadVduVariables, _INR(0, 1), in, in);

    if (!e)
    {
        if (memBuffer) {
            screenBuffer     = (void*)in[0];
            screenBufferSize = xres * yres;
            vid.buffer       = malloc(sWidth * sHeight);
        } else {
            screenBuffer     = NULL;
            screenBufferSize = 0;
            vid.buffer       = (void*)in[0];
        }
        vid.rowbytes     = rowBytes;
        sRowBytes        = rowBytes;
    }
    else
    {
        vid.buffer   = NULL;
        vid.rowbytes = 0;
    }

    return e;
}





void		SWimp_BeginFrame( float camera_separation )
{
}

void		SWimp_EndFrame (void)
{
    int               in[]  = {148, -1};

    if (lineDouble)
    {
        if (memBuffer) {
            int line;
            char * outBuf = screenBuffer;
            char * inBuf  = vid.buffer;
            for(line = 0; line < sHeight; line++) {
                memcpy(outBuf, inBuf, sWidth);
                memcpy(outBuf + sWidth, inBuf, sWidth);
                outBuf += sRowBytes << 1;
                inBuf  += sRowBytes;
            }
        } else {
            int line;
            char * scrBuf  = vid.buffer;
            for(line = 0; line < sHeight; line++) {
                memcpy(scrBuf + sWidth, scrBuf, sWidth);
                scrBuf += sRowBytes;
            }
        }
    } else {
        if (memBuffer) {
            // Update the screen
            memcpy(screenBuffer, vid.buffer, screenBufferSize);
        }
    }

    // Swap screen buffers
    _swix(OS_Byte, _INR(0, 1), 112, bank);
    if (bank == 1) bank = 2; else bank = 1;

    _swix(OS_Byte, _IN(0), 19);
    _swix(OS_Byte, _INR(0, 1), 113, bank);
    _swix(OS_ReadVduVariables, _INR(0, 1), in, in);

    if (memBuffer) {
        screenBuffer = (void*)in[0];
    } else {
        vid.buffer   = (void*)in[0];
    }
}

int			SWimp_Init( void *hInstance, void *wndProc )
{
}

typedef struct
{
  unsigned char padding;
  unsigned char red;
  unsigned char green;
  unsigned char blue;
} paletteentry;

void		SWimp_SetPalette( const unsigned char *palette)
{
    paletteentry pal[256], *palptr;

    int    count;

    palptr = pal;

    for (count = 256; count; count--)
    {
        palptr->red   = *palette++;
        palptr->green = *palette++;
        palptr->blue  = *palette++;
        palette++;
        palptr++;
    }

//    if (displaytype == dm_windowed)
//    {
//      int size;
//      /* Set sprite palette */
//      _swix(ColourTrans_WritePalette, _INR(0, 4), sptarea, sprite, pal, 0, 1);
//      _swix(ColourTrans_SelectTable,  _INR(0, 5) | _OUT(4),
//            sptarea,
//            sprite,
//            -1,
//            -1,
//            NULL,
//            1 | 1<<4,
//            &size);
//      if (transsize < size)
//      {
//        if (transtable) free(transtable);
//        transtable = malloc(size);
//      }
//      _swix(ColourTrans_SelectTable,  _INR(0, 5),
//            sptarea,
//            sprite,
//            -1,
//            -1,
//            transtable,
//            1 | 1 << 4);
//    }
//    else
//    {
      _swix(ColourTrans_WritePalette, _INR(0, 4), -1, -1, pal, 0, 0);
//    }
}

void		SWimp_Shutdown( void )
{
}

rserr_t		SWimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen )
{
    _kernel_oserror * e;
    int in[2], out[2];
    int width, height;
    width  = 320;
    height = 240;

//    printf("SWimp_SetMode(%d, %d, %d, %s)\n", *pwidth, *pheight, mode, fullscreen ? "true" : "false");

    *pwidth  = width;
    *pheight = height;

    e = SetMode(width, height);

    return !e ? rserr_ok : rserr_invalid_fullscreen;
}

void SWimp_AppActivate( qboolean active )
{
}

